﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BTicino.BtCommLib.Mappers;
using BTicino.BtCommLib.Attributes;
using BTicino.BtCommLib.Exceptions;

namespace BTicino.BtCommLib.Test
{
    /// <summary>
    /// This class is used to translate from high level language to BTicino "WHERE"
    /// code parameter and viceversa.
    /// </summary>
    public class MyWhereMapper : IMapper
    {
        // Dictionary from high level to BTicino low level messages, for Lighting system
        private Dictionary<string, string> dictToLowLevel_Light = new Dictionary<string, string>();
        // Dictionary from BTicino low level to high level messages, for Lighting system
        private Dictionary<string, string> dictToHighLevel_Light = new Dictionary<string, string>();

        // Dictionary from high level to BTicino low level messages, for Automation system
        private Dictionary<string, string> dictToLowLevel_Auto = new Dictionary<string, string>();
        // Dictionary from BTicino low level to high level messages, for Automation system
        private Dictionary<string, string> dictToHighLevel_Auto = new Dictionary<string, string>();

        // Dictionary from high level to BTicino low level messages, for bus type
        private Dictionary<string, string> dictBUSToLowLevel = new Dictionary<string, string>();
        // Dictionary from BTicino low level to high level messages, for bus type
        private Dictionary<string, string> dictBUSToHighLevel = new Dictionary<string, string>();

        // Dictionary from high level to BTicino low level messages, for Thermo system
        private Dictionary<string, string> dictToLowLevel_Termo = new Dictionary<string, string>();
        // Dictionary from BTicino low level to high level messages, for Thermo system
        private Dictionary<string, string> dictToHighLevel_Termo = new Dictionary<string, string>();

        public MyWhereMapper()
        {
            // LIGHT
            dictToLowLevel_Light.Add("Bathroom", "21");
            dictToLowLevel_Light.Add("Kitchen", "22");
            dictToLowLevel_Light.Add("Bedroom", "23");
            dictToLowLevel_Light.Add("Dinningroom", "24");
            dictToLowLevel_Light.Add("Office", "11");
            dictToLowLevel_Light.Add("Box", "12");
            // AUTOMATION
            dictToLowLevel_Auto.Add("Bathroom", "19");
            dictToLowLevel_Auto.Add("Kitchen", "28");
            // BUS
            dictBUSToLowLevel.Add("FLOOR1", string.Empty);
            dictBUSToLowLevel.Add("FLOOR2", "#4#02");
            // TERMO
            dictToLowLevel_Termo.Add("Bathroom", "44");
            dictToLowLevel_Termo.Add("Kitchen", "43");

            // LIGHT
            dictToHighLevel_Light.Add("21", "Bathroom");
            dictToHighLevel_Light.Add("22", "Kitchen");
            dictToHighLevel_Light.Add("23", "Bedroom");
            dictToHighLevel_Light.Add("24", "Dinningroom");
            dictToHighLevel_Light.Add("11", "Office");
            dictToHighLevel_Light.Add("12", "Box");
            // AUTOMATION
            dictToHighLevel_Auto.Add("19", "Bathroom");
            dictToHighLevel_Auto.Add("28", "Kitchen");
            // BUS
            dictBUSToHighLevel.Add(string.Empty, "FLOOR1");
            dictBUSToHighLevel.Add("#4#02", "FLOOR2");
            // TERMO
            dictToHighLevel_Termo.Add("44", "Bathroom");
            dictToHighLevel_Termo.Add("43", "Kitchen");
            
        }

        /// <summary>
        /// Traslator from high level message to low level message. For specific messages it need the
        /// HighLevelCtxAttr object to discriminate correct value 
        /// </summary>
        /// <param name="key">Key string, it allows to find low level message associate to specifi high level message</param>
        /// <param name="ctxAttr">Object contains other frame information (eg. WHO, WHAT, etc...)</param>
        /// <returns>Low level message</returns>
        public string GetValueToLowLevel(string key, HighLevelCtxAttr ctxAttr)
        {
            string rtnMsgAddr = string.Empty;
            string rtnMsgBus = string.Empty;
            string[] keys = new string[2];
            keys = key.Split(' ');

            if (ctxAttr.GetCtxAttr(BTAttributeName.Who).Equals(WhoValues.Light.ToString()))
            {
                foreach (string myKey in keys)
                {
                    if (dictToLowLevel_Light.ContainsKey(myKey))
                        rtnMsgAddr = dictToLowLevel_Light[myKey];
                    else if (dictBUSToLowLevel.ContainsKey(myKey))
                        rtnMsgBus = dictBUSToLowLevel[myKey];
                    else
                        throw new LibException("Where not find");
                }
            }
            else if (ctxAttr.GetCtxAttr(BTAttributeName.Who).Equals(WhoValues.Automation.ToString()))
            {
                foreach (string myKey in keys)
                {
                    if (dictToLowLevel_Auto.ContainsKey(myKey))
                        rtnMsgAddr = dictToLowLevel_Auto[myKey];
                    else if (dictBUSToLowLevel.ContainsKey(myKey))
                        rtnMsgBus = dictBUSToLowLevel[myKey];
                    else
                        throw new LibException("Where not find");
                }
            }
            else if (ctxAttr.GetCtxAttr(BTAttributeName.Who).Equals(WhoValues.Termo.ToString()))
            {
                foreach (string myKey in keys)
                {
                    if (dictToLowLevel_Termo.ContainsKey(myKey))
                        rtnMsgAddr = dictToLowLevel_Termo[myKey];
                    else if (dictBUSToLowLevel.ContainsKey(myKey))
                        rtnMsgBus = dictBUSToLowLevel[myKey];
                    else
                        throw new LibException("Where not find");
                }
            }
            else
            {
                throw new LibException("Who index is wrong");
            }

            return rtnMsgAddr + rtnMsgBus;
        }

        /// <summary>
        /// Traslator from low level message to high level message. For specific messages it need the
        /// LowLevelCtxAttr object to discriminate correct value 
        /// </summary>
        /// <param name="key">Key string, it allows to find high level message associate to specifi low level message</param>
        /// <param name="ctxAttr">Object contains other frame information (eg. WHO, WHAT, etc...)</param>
        /// <returns>High level message</returns>
        public string GetValueToHighLevel(string key, LowLevelCtxAttr ctxAttr)
        {
            string rtnMsgAddr = string.Empty;
            string rtnMsgBus = dictBUSToHighLevel[string.Empty];
            string[] keys = new string[2];
            keys = key.Split(' ');

            if (ctxAttr.GetCtxAttr(BTAttributeName.Who).Equals(WhoValues.Light.GetHashCode().ToString()))
            {
                foreach (string myKey in keys)
                {
                    if (dictToHighLevel_Light.ContainsKey(myKey))
                        rtnMsgAddr = dictToHighLevel_Light[myKey];
                    else if (dictBUSToHighLevel.ContainsKey(myKey))
                        rtnMsgBus = dictBUSToHighLevel[myKey];
                    else
                        throw new LibException("Where not find");
                }
            }
            else if (ctxAttr.GetCtxAttr(BTAttributeName.Who).Equals(WhoValues.Automation.GetHashCode().ToString()))
            {
                int index = key.IndexOf('#');
                Console.WriteLine("count:" + key.Length);
                if (index > 0)
                {
                    keys = new string[2];
                    keys[0] = key.Substring(0, index);
                    keys[1] = key.Substring(index);
                }
                foreach (string myKey in keys)
                {
                    if (dictToHighLevel_Auto.ContainsKey(myKey))
                        rtnMsgAddr = dictToHighLevel_Auto[myKey];
                    else if (dictBUSToHighLevel.ContainsKey(myKey))
                        rtnMsgBus = dictBUSToHighLevel[myKey];
                    else
                        throw new LibException("Where not find");
                }
            }
            else if (ctxAttr.GetCtxAttr(BTAttributeName.Who).Equals(WhoValues.Termo.GetHashCode().ToString()))
            {
                int index = key.IndexOf('#');
                Console.WriteLine("count:" + key.Length);
                if (index > 0)
                {
                    keys = new string[2];
                    keys[0] = key.Substring(0, index);
                    keys[1] = key.Substring(index);
                }
                foreach (string myKey in keys)
                {
                    if (dictToHighLevel_Termo.ContainsKey(myKey))
                        rtnMsgAddr = dictToHighLevel_Termo[myKey];
                    else if (dictBUSToHighLevel.ContainsKey(myKey))
                        rtnMsgBus = dictBUSToHighLevel[myKey];
                    else
                        throw new LibException("Where not find");
                }
            }
            else
            {
                throw new LibException("Where not find");
            }
            return rtnMsgAddr + " " + rtnMsgBus;
        }
    }
}